package testplan.services.mock;

import com.google.common.base.Predicate;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.internal.Nullable;
import testplan.entities.Project;
import testplan.entities.Release;
import testplan.entities.TestCase;
import testplan.entities.TestPlan;
import testplan.services.ProjectService;
import testplan.services.TestPlanService;
import testplan.services.UserService;

import static com.google.common.base.Preconditions.*;
import static com.google.common.collect.Collections2.filter;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Singleton
public class MockTestPlanService implements TestPlanService
{
    protected List<TestPlan> testPlanStore = new ArrayList<TestPlan>();
    protected long testPlanKey = 0;
    protected List<TestCase> testCaseStore = new ArrayList<TestCase>();
    protected long testCaseKey = 0;

    @Inject
    public MockTestPlanService(ProjectService projectService, UserService userService)
    {
        checkNotNull(projectService);
        MockProjectService mockProjectService = (MockProjectService) projectService;

        // create a test plan per release per project
        for (Project p : mockProjectService.projectStore)
        {
            // whatever first release object
            for(Release r : mockProjectService.getReleases(p.getKey()))
            {
                createTestPlan(
                        "Demo Plan for " + r.getName(),
                        String.format("Plan created by %s for project \"%s\" release \"%s\".", userService.getDevUser().getName(), p.getName(), r.getName()),
                        p.getKey(), r.getKey(), userService.getDevUser().getKey());
            }
        }
    }

    @Override
    public void createTestPlan(String name, String description, long projectId, long releaseId, long createBy)
    {
        TestPlan testPlan = new TestPlan(name, releaseId, description, createBy, projectId);
        testPlanStore.add(testPlan);
        testPlan.setKey(testPlanKey++);

        // create a demo test case
        addTestCase("Demo test case", String.format("Test case for %s.", name), "1. start.\n2.stop.\n", "pass", createBy, testPlan.getKey());
    }

    @Override
    public Set<TestPlan> getTestPlans(final long projectId)
    {
        return new HashSet<TestPlan>(filter(testPlanStore, new Predicate<TestPlan>()
        {
            @Override
            public boolean apply(@Nullable TestPlan testPlan)
            {
                return testPlan != null && testPlan.getProject() == projectId;
            }
        }));
    }

    @Override
    public Set<TestPlan> getTestPlans(final long projectId, final long releaseId)
    {
        return new HashSet<TestPlan>(filter(testPlanStore, new Predicate<TestPlan>()
        {
            @Override
            public boolean apply(@Nullable TestPlan testPlan)
            {
                return testPlan != null && testPlan.getProject() == projectId && testPlan.getRelease() == releaseId;
            }
        }));
    }

    @Override
    public void addTestCase(String title, String description, String steps, String expectedResults, long createdBy, long planId)
    {
        final TestCase testCase = new TestCase(title, description, steps, expectedResults, createdBy, planId);
        testCaseStore.add(testCase);
        testCase.setKey(testCaseKey++);
    }

    @Override
    public void removeTestCase(long caseId)
    {

    }

    @Override
    public Set<TestCase> getTestCases(final long planId)
    {
        return new HashSet<TestCase>(filter(testCaseStore, new Predicate<TestCase>()
        {
            @Override
            public boolean apply(@Nullable TestCase testCase)
            {
                return testCase != null && testCase.getPlan() == planId;
            }
        }));
    }
}
